﻿using HalconDotNet;
using System.Text;

namespace PointsCloudHandler
{
    public partial class Form1 : Form
    {
        private HDevelopExport export = new HDevelopExport();
        private HWindowControl hwControl;
        private HWindow hWindow;
        private HObject ho_Image;
        private HTuple objectModel3D;
        private HTuple hv_CamParam;
        private HTuple hv_GenParamName;
        private HTuple hv_GenParamValue;
        private HTuple poseOut;
        private HTuple hv_ObjectModel3DIDReduced;
        private HTuple hv_TriangulatedObjectModel3D;

        public Form1()
        {
            InitializeComponent();
        }
        /// <summary>
        /// 初始化Halcon控件并添加到对应容器
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_Load(object sender, EventArgs e)
        {
            // 创建Halcon控件
            hwControl = new HWindowControl();
            // 获取halcon控件上面的窗口对象
            hWindow = hwControl.HalconWindow;
            // 设置halcon控件以填充方式置于容器中
            hwControl.Dock = DockStyle.Fill;
            // 添加控件到对应容器
            panel1.Controls.Add(hwControl);
        }
        /// <summary>
        /// 加载点云图像
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            // 创建对话框
            var dialog = new OpenFileDialog();
            dialog.InitialDirectory = @"C:\Users\LEGION\Desktop\机器视觉\5、3D点云";
            dialog.Filter = "打开点云文件|*.tif";
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                // 获取选择的点云文件路径
                var filePath = dialog.FileName;
                // 创建一个Halcon图像对象
                ho_Image = new HImage(filePath);
                // 把图像显示到Halcon控件的窗口上面
                hWindow.DispObj(ho_Image);
                // 图像自适应容器大小
                //hwControl.SetFullImagePart();
            }
        }

        /// <summary>
        /// 生成3D点云模型
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            // 缩放图像灰度值
            HOperatorSet.ScaleImage(ho_Image, out ho_Image, .001, .0);
            // 放大图像到原来2呗
            HOperatorSet.ZoomImageFactor(ho_Image, out ho_Image, 2, 2, "constant");
            // 把放大图像拆分为3个通道
            HOperatorSet.Decompose3(ho_Image, out HObject x, out HObject y, out HObject z);
            // 生成3D点云模型
            HOperatorSet.XyzToObjectModel3d(x, y, z, out objectModel3D);
            // 持久化生成的3D模型
            HOperatorSet.WriteObjectModel3d(objectModel3D, "om3", "pcl.om3", new HTuple(), new HTuple());
            // 提示生成3D模型成功
            MessageBox.Show("生成3D模型OK");
        }

        /// <summary>
        /// 显示3D模型(很多企业包括开发人员都没有搞定)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            // 创建3D模型显示位姿
            HOperatorSet.CreatePose(0.058, -0.165, 0.660, 345.0, 355.0, 356.0, "Rp+T", "gba", "point", out HTuple hv_Pose);
            // 初始化相机已经参数
            hv_CamParam = new HTuple(0.01, 0, 7e-6, 7e-6, 352, 288, 710, 576);
            // 初始化3D模型显示的颜色，是否显示坐标系，设置透明的元组
            hv_GenParamName = new HTuple("color", "disp_pose", "alpha");
            hv_GenParamValue = new HTuple("green", "false", 0.8);
            // 设置显示字体大小
            export.set_display_font(hWindow, 16, "mono", "true", "false");
            // 读取刚刚持久化的3D模型对象
            HOperatorSet.ReadObjectModel3d("pcl.om3", "m",
                new HTuple(), new HTuple(), out objectModel3D, out HTuple stats);
            // 把窗口对象推窗口栈中
            HDevWindowStack.Push(hWindow);
            // 显示3D模型
            Task.Run(() =>
            {
                export.visualize_object_model_3d(hWindow, objectModel3D, hv_CamParam,
                hv_Pose, hv_GenParamName, hv_GenParamValue, "显示3D点云模型",
                new HTuple(), new HTuple(), out poseOut);
            });
        }

        /// <summary>
        /// 点云数据切割
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button4_Click(object sender, EventArgs e)
        {
            //对3D对象模型应用阈值
            HOperatorSet.SelectPointsObjectModel3d(objectModel3D, "point_coord_z",
                0.5, 0.67, out hv_ObjectModel3DIDReduced);
            // 三角化，对其分割好的点云数据实现三维重建
            HOperatorSet.TriangulateObjectModel3d(hv_ObjectModel3DIDReduced, "greedy", new HTuple(),
                new HTuple(), out hv_TriangulatedObjectModel3D, out HTuple information);
            // 显示3D模型
            Task.Run(() =>
            {
                export.visualize_object_model_3d(hWindow, hv_TriangulatedObjectModel3D, hv_CamParam,
                poseOut, hv_GenParamName, hv_GenParamValue, "显示3D点云模型",
                new HTuple(), new HTuple(), out poseOut);
            });
        }

        /// <summary>
        /// 对象重建后的点云模型分割区域分别计算直径和体积
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button5_Click(object sender, EventArgs e)
        {
            // 通过阈值联通区域
            HOperatorSet.ConnectionObjectModel3d(hv_TriangulatedObjectModel3D, "distance_3d",
                0.01, out HTuple hv_ObjectModel3DIDConnections);
            // 设置不同连通区域显示颜色
            if (hv_GenParamName == null)
                hv_GenParamName = new HTuple();
            hv_GenParamName[0] = "colored";
            if (hv_GenParamValue == null)
                hv_GenParamValue = new HTuple();
            hv_GenParamValue[0] = 12;

            // 测试体积
            HOperatorSet.VolumeObjectModel3dRelativeToPlane(hv_ObjectModel3DIDConnections, ((((new HTuple(0)).TupleConcat(0)).TupleConcat(0.67))).TupleConcat(
              (((new HTuple(0)).TupleConcat(0)).TupleConcat(0)).TupleConcat(0)), "signed", "true", out HTuple hv_Volume);
            // 计算直径
            HOperatorSet.MaxDiameterObjectModel3d(hv_ObjectModel3DIDConnections, out HTuple hv_Diameter);
            HTuple hv_ResultMessage = "  #  Max. diameter    Volume";
            // 显示编号
            var hv_Indices = HTuple.TupleGenSequence(0, (new HTuple(hv_ObjectModel3DIDConnections.TupleLength())) - 1, 1);
            // 显示序列
            var hv_Sequence = HTuple.TupleGenSequence(0, (new HTuple(hv_ObjectModel3DIDConnections.TupleLength())) - 1, 1);
            // 显示结果
            HTuple ExpTmpLocalVar_ResultMessage = hv_ResultMessage.TupleConcat((((((hv_Sequence.TupleString(" 3")) + "     ") +
                (((hv_Diameter * 1e3)).TupleString("7.1f"))) + " mm  ") + (((hv_Volume * 1e3)).TupleString("7.3f"))) + " dm³");
            // 创建字符串构建对象
            var sb = new StringBuilder();
            for (int i = 0; i < ExpTmpLocalVar_ResultMessage.Length; i++)
            {
                sb.Append(ExpTmpLocalVar_ResultMessage[i].S + "\r\n");
            }
            textBox1.Text = sb.ToString();
            // 显示分割的后的模型
            Task.Run(() =>
            {
                export.visualize_object_model_3d(hWindow, hv_ObjectModel3DIDConnections, hv_CamParam,
                    poseOut, hv_GenParamName, hv_GenParamValue, "分割后的3D模型", "#" + hv_Indices, new HTuple(), out poseOut);
            });
        }
    }
}